
package com.scalar.chiptrack.users.actions;

import java.util.Enumeration;
import java.util.HashMap;
import java.util.LinkedHashMap;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;

import org.apache.struts.action.ActionForm;
import org.apache.struts.action.ActionForward;
import org.apache.struts.action.ActionMapping;

import com.scalar.ScalarException;
import com.scalar.chiptrack.ChipTrackAction;
import com.scalar.chiptrack.commons.Constants;
import com.scalar.chiptrack.commons.SessionKeys;
import com.scalar.chiptrack.db.DBTransaction;
import com.scalar.chiptrack.users.FunctionAccess;
import com.scalar.chiptrack.users.dao.UserDAO;
import com.scalar.chiptrack.users.forms.UserSetupForm;
import com.scalar.chiptrack.utils.ConfigManager;
import com.scalar.chiptrack.utils.Mailer;
import com.scalar.chiptrack.utils.MessageDigestUtils;
import com.scalar.chiptrack.utils.StringUtils;


public class UserSetupAction extends ChipTrackAction
{
    public ActionForward execute ( ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response ) throws Exception
    {
        HashMap<String, String> errors          = new HashMap<String, String>();
		HashMap<String, String> info            = new HashMap<String, String>();
        boolean success     = false;
        HttpSession session = request.getSession();
        request.setAttribute( SessionKeys.INFO_MESSAGES, info );
        request.setAttribute ( SessionKeys.ERROR_MESSAGES, errors );
        if ( ( session == null ) || ( session.getAttribute( SessionKeys.USER_KEY ) == null ) )
        {
            return ( mapping.findForward( "login" ) );
        }

        UserSetupForm userSetupForm = ( UserSetupForm ) form;

        HashMap formErrors = validateForm (userSetupForm);

        if( ( formErrors != null ) && ( formErrors.isEmpty() == false ) )
        {
            request.setAttribute( "userSetupForm", userSetupForm );
            request.setAttribute( SessionKeys.ERROR_MESSAGES, formErrors );
            return ( mapping.findForward( "failure" ) );
        }

        String userId       = userSetupForm.getUserId();
        String password     = userSetupForm.getPassword();
        String firstName    = userSetupForm.getFirstName();
        String lastName     = userSetupForm.getLastName();
        String phoneNumber  = userSetupForm.getPhoneNumber();
        String faxNumber    = userSetupForm.getFaxNumber();
        String email        = userSetupForm.getEmail();
        int userGroupId     = Integer.parseInt( userSetupForm.getUserGroupId() );
        int levelId         = Integer.parseInt( userSetupForm.getLevelId() );
        int regionId        = userSetupForm.getRegionId();
        String expiresOn    = userSetupForm.getExpiresOn();
        String receiveNotifications = userSetupForm.getReceiveNotifications();

        boolean isUpdate = new Boolean( request.getParameter ("isUpdate") ).booleanValue();

        HashMap functionAccessMap = new HashMap();

        Enumeration paramNames          = request.getParameterNames();
        String levelName                = null;
        String level                    = null;

        FunctionAccess functionAccess   = null;
        int functionId                  = -1;
        int groupId                     = -1;
        String action                   = null;

        int firstIndex                  = -1;
        int secondIndex                 = -1;
        int lastIndex                   = -1;

        success = true; // if the flow skips this while loop..
        while( paramNames.hasMoreElements() )
        {
            levelName = (String) paramNames.nextElement();

            if( levelName.startsWith( "FUNCTION_ID" ) == true )
            {
                level = request.getParameter( levelName );

                if ( "on".equalsIgnoreCase( level ) == true )
                {

                    try
                    {
                        firstIndex  = levelName.indexOf(',');
                        secondIndex = levelName.indexOf (',', firstIndex+1);
                        lastIndex   = levelName.lastIndexOf(',');

                        functionId  = Integer.parseInt( levelName.substring( ( firstIndex + 1 ), secondIndex ) );
                        groupId     = Integer.parseInt( levelName.substring( ( secondIndex + 1 ), lastIndex ) );
                        action      = levelName.substring( lastIndex + 1 );

                        functionAccess = ( FunctionAccess ) functionAccessMap.get( "" + functionId );
                        if( functionAccess == null )
                        {
                            functionAccess = new FunctionAccess();
                            functionAccess.setFunctionId( functionId );
                            functionAccess.setGroupId( groupId );
                            functionAccess.setUserlId( userId );

                            functionAccessMap.put ( "" + functionId, functionAccess );
                        }

                        if( action.equalsIgnoreCase( "view" ) == true )
                        {
                            functionAccess.setView( true );
                        }
                        else if( action.equalsIgnoreCase( "modify" ) == true )
                        {
                            functionAccess.setModify( true );
                        }
                        else if( action.equalsIgnoreCase( "delete" ) == true )
                        {
                            functionAccess.setDelete( true );
                        }
                        success = true;
                    }
                    catch ( Exception e )
                    {
                        success = false;
                        e.printStackTrace ();
                        errors.put ("Invalid Values found while parsing for Function Access Levels", null);
                        request.setAttribute (SessionKeys.ERROR_MESSAGES, errors);
                    }
                }
            }

        }

        if( success == false )
        {
            return ( mapping.findForward( "failure" ) );
        }

        success = false;
        DBTransaction dbTransaction = null;
        try
        {
			boolean checkValue = true;

            // Encrypt password before stroing it -- one way encryption
            String encryptedPassword = null;
            if( ( password != null ) && ( password.trim().length() != 0 ) )
            {
                encryptedPassword = StringUtils.concatBytes( MessageDigestUtils.getMAC ( password ), "," );
            }
            if ( regionId == -2)
            {
                if (UserDAO.doesRegionIdExist( null, "" + userSetupForm.getNewRegion() ) )
                {
                    request.setAttribute("ErrorInSaving","True");
                    request.setAttribute("ErrorInRegionSaving","True");
                    errors.put("Region Name <font color=blue>"+userSetupForm.getNewRegion()+" </font> already exists, please enter another Reason ", null);
                    return( mapping.findForward( "failure" ) );

                }
                else
                {
                    regionId = UserDAO.insertNewRegion( null, userSetupForm.getNewRegion() );
                }
            }
            // Start transaction
            dbTransaction = DBTransaction.getInstance();
            dbTransaction.begin();

            if( isUpdate == true )
            {
                //System.out.println ("updating user settings for " + userId);
                UserDAO.updateUserSettings (dbTransaction, userId, encryptedPassword, firstName, lastName, phoneNumber, faxNumber, userGroupId, levelId, regionId, email, expiresOn, receiveNotifications,
                                            userSetupForm.getSalesAckMail(),
                                            userSetupForm.getShipAlerts() ,
                                            userSetupForm.getProformaInvoice() ,
                                            userSetupForm.getPackingSlip(), userSetupForm.isQuoteAckMail(), userSetupForm.isRmaAckMail(), Constants.USER_TYPE_CHIPTRAC );

                UserDAO.insertFunctionAccessList ( dbTransaction, isUpdate, userId, functionAccessMap.values().iterator() );

                info.put( "Setup information for " + userId + " has been saved successfully", null );
			    //request.setAttribute( SessionKeys.INFO_MESSAGES, info );
                success = true;
            }
            else
            {
                // insert a row into address table for this user.. later updated by the user from Profile page
                int addressId = UserDAO.insertAddress ( dbTransaction, ""/*address1*/, ""/*address2*/, ""/*city*/, ""/*state*/, ""/*zipcode*/, "" /*country*/ );

                //To check whether userId already exists ot not
				checkValue = UserDAO.doesUserIdExist( dbTransaction, "" + userId );
				if( checkValue == false )
				{
                    UserDAO.insertUser (dbTransaction, userId, encryptedPassword, firstName, lastName, userGroupId, levelId, addressId, regionId, email, phoneNumber, faxNumber, expiresOn, receiveNotifications,
                                      userSetupForm.getSalesAckMail(),
                                      userSetupForm.getShipAlerts() ,
                                      userSetupForm.getProformaInvoice() ,
                                      userSetupForm.getPackingSlip(), userSetupForm.isQuoteAckMail(), userSetupForm.isRmaAckMail(), Constants.USER_TYPE_CHIPTRAC );

                    UserDAO.insertFunctionAccessList( dbTransaction, isUpdate, userId, functionAccessMap.values().iterator() );


					info.put( "Setup information for " + userId + " has been saved successfully", null );
					//request.setAttribute( SessionKeys.INFO_MESSAGES, info );

					success = true;
				}
				else
				{
                    request.setAttribute("ErrorInRegionSaving","false");
				    request.setAttribute("ErrorInSaving","True");
				}
            }
        }
        catch (ScalarException se)
        {
            System.out.println ("exception = " + se);
            String error = "Could not save - " + userId + "'s information";
            if( se.getRootCause().getMessage().indexOf ( "Violation of PRIMARY KEY constraint" ) != -1 ) 
            {
                error += ", Cannot use this user ID. Please choose different user ID";
            }
            errors.put (error, null);
            //request.setAttribute(SessionKeys.ERROR_MESSAGES, errors);

            System.out.println ("Exception while storing user inforamtion.. \n" + se.getRootCause().getMessage() + "\nRolling back");
            se.printStackTrace();
        }
        finally
        {
            if ( dbTransaction != null )
            {
                if (success == true)
                {
                    dbTransaction.commit();
                }
                else
                {
                    dbTransaction.rollback();
                }
            }    
        }

        if( isUpdate == true )
        {
            if (session.getAttribute("groupList") == null)
            {
                session.setAttribute ("groupList", UserDAO.loadAllUserGroups());
            }
            session.setAttribute ("userList", UserDAO.loadAllUsers (true/*load expired and disabled users*/,Constants.USER_TYPE_CHIPTRAC));
            return (mapping.findForward ("maintainUser"));
        }
        if( success )
        {
            if ( "on".equalsIgnoreCase( userSetupForm.getNotifyUser() ) == true )
            {
                try
                {
                    // Notify the user about his userId, password and email
                    String host = request.getHeader ("HOST");
                    notifyUser (host, userSetupForm);
                    info.put ("Setup Information has been sent to " + userSetupForm.getEmail(), null);
                    //request.setAttribute (SessionKeys.INFO_MESSAGES, info);
                    success = true;
                }
                catch (Exception e)
                {
                    success = false;
                    // Exception while sending mail to the user
                    errors.put ("Could not send email to the user about the setup information", null);
                    //request.setAttribute (SessionKeys.ERROR_MESSAGES, errors);
                    request.setAttribute("userSetupForm",null);
                }
            }

            if( success )
            {
                request.setAttribute( "userSetupForm", null );
                return( mapping.findForward( "success" ) );
            }
        }

        return( mapping.findForward( "failure" ) );
    }



    private void notifyUser (String host, UserSetupForm userSetupForm) throws Exception {

        String from = ConfigManager.getSysAdminEmail();
        String to = userSetupForm.getEmail();
        String subject = "Welcome to ChipTrac System";

        // FORMAT MESSAGE
        StringBuffer buf = new StringBuffer (2098);

        buf.append ("<HTML><HEAD><TITLE>Scalarsoft - ChipTrac</TITLE><BR>\n");
        buf.append ("<link href='http://").append (host).append ("/").append (ConfigManager.getChipTracContext()).append ("/jsp/includes/stylesheets/scalarsoft.css' type=text/css rel=stylesheet><BR>\n");
        buf.append ("</HEAD><BODY bgColor='#ffffff' leftMargin=0 topMargin=0 marginheight='0' marginwidth='0'><BR>\n");
        buf.append ("<table border=0><tr><td width=10%>&nbsp;</td><td width=90%><table border=0><tr><td>");
        buf.append ("<IMG src='http://").append (host).append ("/").append(ConfigManager.getChipTracContext()).append("/jsp/includes/images/scalar_logo.jpg' width=90 height=36 border=0><BR>\n");
        buf.append ("<BR><BR>A new user account has been created for you in the <B>ChipTrac</B> System.");
        buf.append ("<BR><BR><BR>Login: <B>").append (userSetupForm.getUserId()).append ("</B>\n");
        buf.append ("<BR>Password: <B>").append (userSetupForm.getPassword()).append("</B>\n<br>\n");
        buf.append ("Please Click <a href='http://").append (host).append ("/").append (ConfigManager.getChipTracContext()).append ("/jsp/index.jsp'>here</a> to log into the system.");
        buf.append ("<br><br><p><u><b>Message from the System Administrator:</b></u>\n");
        buf.append ("<pre>").append (userSetupForm.getMessageToUser()).append ("</pre><br><br>");
        buf.append ("</td></tr></td><tr></table>\n");
        buf.append ("</BODY>\n");
        buf.append ("</HTML>\n");

        String message = buf.toString();

        // SEND MESSAGE
        Mailer.send (from, to, subject, message, Mailer.CONTENT_TYPE_HTML);
    }


    private HashMap validateForm (UserSetupForm userSetupForm) {

        HashMap errors = new LinkedHashMap();

        String userId = userSetupForm.getUserId();
        String password = userSetupForm.getPassword();
        String password1 = userSetupForm.getPassword1();
        String firstName = userSetupForm.getFirstName();
        String lastName = userSetupForm.getLastName();
        String email = userSetupForm.getEmail();
        String userGroupId = userSetupForm.getUserGroupId();

        if ((userId == null) || (userId.trim().length() == 0)) {
            errors.put ("User ID", "User ID required");
           // System.out.println ("User ID required");
        }

        if ((password != null) && (password.equals (password1) == false)) {
            errors.put ("Password", "Password did not match");
        }

        if ((firstName != null) && (firstName.trim().length() == 0)) {
            errors.put ("First Name", "First Name Required");
        }

        if ((email == null) || (email.trim().length() == 0)) {
            errors.put ("Email", "Email required");
        }
        else if (email.indexOf("@") == -1) {
            errors.put ("Email", "Invalid Email");
        }

        if ((userGroupId == null) || (userGroupId.trim().length() == 0) || (userGroupId.equalsIgnoreCase("-1"))) {
            errors.put ("User Group", "Select user group");
        }

        return errors;
    }
}